/**
 * CoffeeMilk (C) 2010 Amen Hamdan
 * 
 * See the NOTICE file distributed with this work for additional 
 * information regarding copyright ownership.  This file is licenses
 * to you under the Apache License, Version 2.0 (the "License"); you 
 * may not use this file except in compliance with the License.  You 
 * may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 *     
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
 * implied. See the License for the specific language governing 
 * permissions and limitations under the License.    
 * 
 */
package ameen.rtm.coffeemilk.setup;

import java.awt.Desktop;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URI;

import javax.swing.JButton;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

import ameen.rtm.coffeemilk.persistency.PersistencyManager;
import ameen.rtm.coffeemilk.persistency.SettingsStore;
import ameen.rtm.lib.RtmException;
import ameen.rtm.lib.RtmService;
import ameen.rtm.lib.RtmService.AccessPermission;
import ameen.rtm.lib.types.AuthToken;

public class SetupWizard {
	private SetupWizardFrame setupWizardFrame = new SetupWizardFrame();
	private RtmService fRtmService;
	private SettingsStore fSettingsStore;

	public void clearMouseListeners() {
		JButton button = setupWizardFrame.getBackButton();
		for(MouseListener listener : button.getMouseListeners()) {
			button.removeMouseListener(listener);
		}
		button = setupWizardFrame.getNextButton();
		for(MouseListener listener : button.getMouseListeners()) {
			button.removeMouseListener(listener);
		}
	}
	
	public SetupWizardFrame getSetupWizardFrame() {
		return setupWizardFrame;
	}

	public void startSetupWizard(RtmService rtmService, SettingsStore settingsStore) {
		fRtmService = rtmService;
		fSettingsStore = settingsStore;

		setupWizardFrame.getCancelButton().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				setupWizardFrame.dispose();
			}
		});
		setupWizardFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		setupWizardFrame.setVisible(true);
		setStateIntro();
	}

	private void setStateIntro() {
		clearMouseListeners();
		
		setupWizardFrame.getUrlPanelInfo().setVisible(false);
		setupWizardFrame.getHeadingLabel().setText("Welcome to CoffeeMilk.");
		setupWizardFrame.getDescriptionTextArea().setText(
				"This setup wizard will help you link your Remember the Milk account with this application." +
				"You may cancel this process at any time and can revoke this link later. \n\nPlease press 'Next' to proceed");
		
		setupWizardFrame.getBackButton().setEnabled(false);
		setupWizardFrame.getNextButton().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				setStateFrobRequest();
			}
		});
		
	}

	private void setStateFrobRequest() {
		clearMouseListeners();
		
		try {
			String frob = fRtmService.getFrob();
			fSettingsStore.setFrob(frob);
			final String authUrl = fRtmService.createAuthUrl(frob, AccessPermission.DELETE);

			setupWizardFrame.getBackButton().setEnabled(true);
			setupWizardFrame.getNextButton().setEnabled(true);
			setupWizardFrame.getUrlPanelInfo().setVisible(true);
			setupWizardFrame.getUrlLabel().setText(authUrl);
			setupWizardFrame.getCopyClipboardButton().addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
					StringSelection selection = new StringSelection(authUrl);
					clipboard.setContents(selection, null);
				}
			});
			
			setupWizardFrame.getHeadingLabel().setText("Link CoffeeMilk to Remember The Milk.");
			setupWizardFrame.getDescriptionTextArea().setText(
					"CoffeeMilk will now try to open a browser to point it at the Remember the Milk web site. You will be requested to grant " +
					"this application permission to access your data. " +
					"If the URL does not open correctly, please point your browser manually to the URL given below." +
					"\n\nPlease press 'Next' once you completed the autorization on the web site to proceed."							
			); 

			(new Thread() {
				public void run() {
					try {
						Desktop.getDesktop().browse(new URI(authUrl));
					} catch (Exception e) {
						e.printStackTrace();
					}
				};
			}).start();
				
			
			setupWizardFrame.getBackButton().setEnabled(true);
			setupWizardFrame.getBackButton().addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					setStateIntro();
				}
			});


			setupWizardFrame.getNextButton().addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					setStateFinished();
				}
			});
		} catch (RtmException rtme) {
			rtme.printStackTrace();
		}
		
			
	}
	
	private void setStateAuthenticationFailed() {
		clearMouseListeners();
		
		setupWizardFrame.getUrlPanelInfo().setVisible(false);
		setupWizardFrame.getHeadingLabel().setText("Authentication Failed.");
		setupWizardFrame.getNextButton().setEnabled(false);
		setupWizardFrame.getDescriptionTextArea().setText(
				"The authentication of this application failed. Please return by pressing the 'Back' button. " +
				"Follow the instructions given and try again.");
		
		setupWizardFrame.getBackButton().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				SwingUtilities.invokeLater(new Runnable() {
					
					@Override
					public void run() {
						setStateFrobRequest();
					}
				});
			}
		});
	}
	
	private void setStateFinished() {
		clearMouseListeners();
		
		setupWizardFrame.getUrlPanelInfo().setVisible(true);
		try {
			AuthToken authToken = fRtmService.getToken(fSettingsStore.getFrob());
		
			setupWizardFrame.getUrlPanelInfo().setVisible(false);
			setupWizardFrame.getHeadingLabel().setText("Setup complete.");
			
			setupWizardFrame.getNextButton().setEnabled(true);
			setupWizardFrame.getNextButton().setText("Finish");
			
			setupWizardFrame.getBackButton().setEnabled(false);
			setupWizardFrame.getCancelButton().setEnabled(false);
			setupWizardFrame.getDescriptionTextArea().setText("Authentication / setup completed. You may now use CoffeeMilk.");

			setupWizardFrame.getNextButton().addMouseListener(new MouseAdapter() {
				@Override
				public void mouseClicked(MouseEvent e) {
					setupWizardFrame.dispose();
				}
			});
			
			fSettingsStore.setAuthToken(authToken);
			
			if(!fRtmService.checkSettings()) {
				setStateAuthenticationFailed();
			}
			
			PersistencyManager.writeSettings(fSettingsStore);
			
		} catch (RtmException e) {
			setStateAuthenticationFailed();
		}
	}
}
